import axios from 'axios'
import { queryGroupList } from '../api'
import _moment from 'moment'

/**
 * [getValueByKey description] 根据keyValue字符串中key获取value
 * @param  {String} keyValueStr [keyValue字符串]
 * @param  {String} spliter     [分隔符,字符串或者正则表达式]
 * @return {[Function]}         [返回一个可以传入key获取value的函数]
 * 使用方法 const getCookie = getValueByKey(document.cookie, '; ')
 *          const getQueryString = getValueByKey(document.location.href.replace(/^.*\?/, ''), /\&|\#/)
 */
export const getValueByKey = function (keyValueStr = '', spliter = ';') {
  let i = 0
  let n = 0
  let keyPair = []
  let keyPairs = []
  const keyValues = {}

  keyPairs = keyValueStr.split(spliter)
  for (i = 0, n = keyPairs.length; i < n; i++) {
    keyPair = keyPairs[i].split('=')
    if (keyPair[0]) {
      keyValues[keyPair[0]] = keyPair[1] || ''
    }
  }

  return (key) => (keyValues[key] || '')
}

export const getCookie = function (cookieKey) {
  const cookieString = document.cookie
  const keyPairs = cookieString.split('; ')
  let cookieValue = ''

  for (let i = 0, n = keyPairs.length; i < n; i++) {
    let keyPair = keyPairs[i].split('=')
    if (keyPair[0] === cookieKey) {
      cookieValue = keyPair[1] || ''
      break
    }
  }

  return cookieValue
}

export const platform = {
  is: function (tag, navigator) {
    // "iPhone", "iPod", "iPad", "Blackberry", "Android", "wp",
    // "Mac", "Windows", "Linux", "Desktop", "Tablet",
    // "Phone", "iOS", "Standalone"
    const _navigator = navigator || window.navigator
    const platforms = [
      {
        property: 'platform',
        regex: /iPhone/i,
        identity: 'iPhone'
      },
      {
        property: 'platform',
        regex: /iPod/i,
        identity: 'iPod'
      },
      {
        property: 'userAgent',
        regex: /iPad/i,
        identity: 'iPad'
      },
      {
        property: 'userAgent',
        regex: /Blackberry/i,
        identity: 'Blackberry'
      },
      {
        property: 'userAgent',
        regex: /Android/i,
        identity: 'Android'
      },
      {
        property: 'userAgent',
        regex: /Windows\sPhone/i,
        identity: 'wp'
      },
      {
        property: 'platform',
        regex: /Mac/i,
        identity: 'Mac'
      },
      {
        property: 'platform',
        regex: /Win/i,
        identity: 'Windows'
      },
      {
        property: 'platform',
        regex: /Linux/i,
        identity: 'Linux'
      }
    ]
    let platformIs = {}

    for (let i = 0, n = platforms.length; i < n; i++) {
      let _platfrom = platforms[i]
      platformIs[_platfrom.identity] = _platfrom.regex.test(_navigator[_platfrom.property])
    }
    // @property Desktop True if the browser is running on a desktop machine
    platformIs.Desktop = platformIs.Mac || platformIs.Windows || (platformIs.Linux && !platformIs.Android)
    // @property Tablet True if the browser is running on a tablet (iPad)
    platformIs.Tablet = platformIs.iPad
    // @property Phone True if the browser is running on a phone.
    platformIs.Phone = !platformIs.Desktop && !platformIs.Tablet
    // @property iOS True if the browser is running on iOS
    platformIs.iOS = platformIs.iPhone || platformIs.iPad || platformIs.iPod
    // @property Standalone Detects when application has been saved to homescreen.
    platformIs.Standalone = !!window.navigator['standalone']

    return platformIs[tag] || false
  }
}

export const browser = {
  is: function (tag) {
    const userAgent = window.window.navigator.userAgent
    const upperCaseTag = tag.toUpperCase()
    const browserTypes = {
      UC: function () {
        return (/UCBrowser/).test(userAgent)
      },
      HUAWEI: function () {
        return (/HUAWEI/).test(userAgent)
      }
    }

    return browserTypes[upperCaseTag] ? browserTypes[upperCaseTag]() : false
  }
}

/**
 * [backToHost description] 返回宿主页面
 * @return {[true]} [description]
 */
export const backToHost = function () {
  const webContainer = (platform.is('iPhone') ? window.navigator.WebContainer : window.WebContainer) || {}
  webContainer.backToHomePage()
  webContainer.setAppTitleBarStatus('2')
  return false
}

/**
 * [isSupportGetLocation 判断当前和飞信是否支持位置api]
 * @return {Boolean} [description]
 */
export const isSupportGetLocation = function () {
  const webContainer = (platform.is('iPhone') ? window.navigator.WebContainer : window.WebContainer) || {}

  return webContainer.rcsGetCurrentLocation
}

export const validateGroupName = ({enterId, groupName}, callback) => {

  // 获取当前企业所有考勤组信息
  queryGroupList({enterId}, (err, data) => {
    try {
      if (err) {
        console.error(JSON.stringify(err))
        callback(true)
        return false
      }
      callback(data['var'].findIndex(item => item.attendanceName === groupName) > -1)
    } catch (e) {
      callback(true)
    }
  })

}

// 重新封装 ajax 请求方法
export const request = options => {
  axios({
    baseURL: options.baseURL || '/',
    url: options.url,
    data: options.data,
    headers: options.headers || {
      'Content-Type': 'application/json;charset=utf-8'
    },
    method: options.method || 'post',
    responseType: options.responseType || 'json'
  }).then(res => {
    if (res.status === 200 && res.data) {
      options.success && options.success(res.data)
    } else {
      options.fail && options.fail(res.data)
    }
  }).catch(err => {
    options.fail && options.fail(err)
  })
}

export const requestV2 = (options) => {
  const callback = options.callback || function () { console.log(arguments[0])}
  axios({
    baseURL: options.baseURL || '/',
    url: options.url,
    data: options.data,
    headers: options.headers || {'Content-Type': 'application/json;charset=utf-8'},
    method: options.method || 'post',
    responseType: options.responseType || 'json'
  }).then((res) => {
    try {
      // console.log('timpstamp => ', Date.now())
      // console.log('res ...')
      // console.log(res.data)
      if (res.data && res.data.code === 'S_OK') {
        callback(null, res.data)
      } else if (res.data) {
        callback(res.data)
      } else {
        callback({code: 'RESPONSE_PARSE_ERROR', msg: '响应数据格式解析失败！'})
      }
    } catch (err) {
      console.error(err)
      callback({code: 'CALLBACK_ERROR', msg: '回调函数异常！', error: err})
    }
  }).catch(err => {
    console.log('catch err ...')
    options.callback && options.callback({code: 'AJAX_ERROR', msg: '网络异常!', error: err})
  })
}

/**
 * [获取分钟数]
 * @param  {[type]} time    [description]
 * @param  {String} spliter [description]
 * @return {[type]}         [description]
 * getMinuntes('08:30') => 510
 * getMinuntes('11:30') => 690
 */
export const getMinuntes = (time, spliter = ':') => {
  const arr = time.split(spliter)
  const hours = +arr[0]
  const minutes = +arr[1]

  return hours*60 + minutes
}

/**
 * [计算一天中两个时间点的分钟间隔]
 * @param  {[string]} start ['08:30']
 * @param  {[string]} end   ['11:30']
 * @return {[number]}       [间隔分钟数]
 * getTimeGap('08:30', '11:30') => 180
 */
export const getTimeGap = (start, end) => {
  const startMinutes = getMinuntes(start)
  const endMinutes = getMinuntes(end)

  return endMinutes - startMinutes
}

/**
 * [针对分钟操作'+'/'-']
 * @param  {[type]} time    ['08:30']
 * @param  {[type]} minutes [30]
 * @return {[type]}         [description]
 * 减去分钟时 minutes 传入负数就好
 * mutateMinutes('08:30', 30) => '09:00'
 * mutateMinutes('08:30', -30) => '08:00'
 */
export const mutateMinutes = (time, minutes) => {
  let hh = ''
  let mm = ''
  let timeInMinutes = getMinuntes(time)

  timeInMinutes = timeInMinutes + minutes
  hh = Math.floor((timeInMinutes / 60))
  mm = timeInMinutes % 60

  return (hh < 10 ? '0' + hh : hh) + ':' + (mm < 10 ? '0' + mm : mm)
}

/**
 * [stringValidator 验证字符串格式]
 * @type {Object}
 */
export const stringValidator = {
  msg: {
    // 非字符串
    NON_STRING: 'NON_STRING',
    // 空字符串
    EMPTY_STRING: 'EMPTY_STRING'
  },
  isString:function (str) {
    return Object.prototype.toString.call('') === '[object String]'
  },
  isEmpty:function (str) {
    return str === ''
  },
  commonCheck:function (str) {
    if (!this.isString(str)) {
      throw new Error({type: this.msg['NON_STRING']})
    }

    return true
  },
  isEmail:function (str) {
    this.commonCheck(str)
    return (/^[A-Z0-9._%&'+-]+@[A-Z0-9.-]+\.[A-Z]{2,8}$/i).test(str)
  }
}

// 统一管理moment
export const moment = _moment

const isObject = function (value) {
  const type = typeof value;
  return value != null && (type == 'object' || type == 'function');
}

/**
 * [debounce 从https://raw.githubusercontent.com/lodash/lodash/master/debounce.js拷贝过来]
 * @param  {[type]} func    [description]
 * @param  {[type]} wait    [description]
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
export const debounce =  function (func, wait, options) {
  let lastArgs,
    lastThis,
    maxWait,
    result,
    timerId,
    lastCallTime

  let lastInvokeTime = 0
  let leading = false
  let maxing = false
  let trailing = true

  // Bypass `requestAnimationFrame` by explicitly setting `wait=0`.
  const useRAF = (!wait && wait !== 0 && typeof root.requestAnimationFrame === 'function')

  if (typeof func != 'function') {
    throw new TypeError('Expected a function')
  }
  wait = +wait || 0
  if (isObject(options)) {
    leading = !!options.leading
    maxing = 'maxWait' in options
    maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait
    trailing = 'trailing' in options ? !!options.trailing : trailing
  }

  function invokeFunc(time) {
    const args = lastArgs
    const thisArg = lastThis

    lastArgs = lastThis = undefined
    lastInvokeTime = time
    result = func.apply(thisArg, args)
    return result
  }

  function startTimer(pendingFunc, wait) {
    if (useRAF) {
      return root.requestAnimationFrame(pendingFunc)
    }
    return setTimeout(pendingFunc, wait)
  }

  function cancelTimer(id) {
    if (useRAF) {
      return root.cancelAnimationFrame(id)
    }
    clearTimeout(id)
  }

  function leadingEdge(time) {
    // Reset any `maxWait` timer.
    lastInvokeTime = time
    // Start the timer for the trailing edge.
    timerId = startTimer(timerExpired, wait)
    // Invoke the leading edge.
    return leading ? invokeFunc(time) : result
  }

  function remainingWait(time) {
    const timeSinceLastCall = time - lastCallTime
    const timeSinceLastInvoke = time - lastInvokeTime
    const timeWaiting = wait - timeSinceLastCall

    return maxing
      ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke)
      : timeWaiting
  }

  function shouldInvoke(time) {
    const timeSinceLastCall = time - lastCallTime
    const timeSinceLastInvoke = time - lastInvokeTime

    // Either this is the first call, activity has stopped and we're at the
    // trailing edge, the system time has gone backwards and we're treating
    // it as the trailing edge, or we've hit the `maxWait` limit.
    return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
      (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait))
  }

  function timerExpired() {
    const time = Date.now()
    if (shouldInvoke(time)) {
      return trailingEdge(time)
    }
    // Restart the timer.
    timerId = startTimer(timerExpired, remainingWait(time))
  }

  function trailingEdge(time) {
    timerId = undefined

    // Only invoke if we have `lastArgs` which means `func` has been
    // debounced at least once.
    if (trailing && lastArgs) {
      return invokeFunc(time)
    }
    lastArgs = lastThis = undefined
    return result
  }

  function cancel() {
    if (timerId !== undefined) {
      cancelTimer(timerId)
    }
    lastInvokeTime = 0
    lastArgs = lastCallTime = lastThis = timerId = undefined
  }

  function flush() {
    return timerId === undefined ? result : trailingEdge(Date.now())
  }

  function pending() {
    return timerId !== undefined
  }

  function debounced(...args) {
    const time = Date.now()
    const isInvoking = shouldInvoke(time)

    lastArgs = args
    lastThis = this
    lastCallTime = time

    if (isInvoking) {
      if (timerId === undefined) {
        return leadingEdge(lastCallTime)
      }
      if (maxing) {
        // Handle invocations in a tight loop.
        timerId = startTimer(timerExpired, wait)
        return invokeFunc(lastCallTime)
      }
    }
    if (timerId === undefined) {
      timerId = startTimer(timerExpired, wait)
    }
    return result
  }
  debounced.cancel = cancel
  debounced.flush = flush
  debounced.pending = pending
  return debounced
}
